home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 04 - 1988 / 04.11 Nov 88 / IAC / Editor Stuff / Doc_rtns.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-21  |  13.9 KB  |  485 lines  |  [TEXT/MPS ]

  1. /****
  2.  *
  3.  *    These are the routines required to actually carry out the document-handling
  4.  *    functions. They are invoked from menu_tree() and are arranged in alphabetic
  5.  *    order to simplify finding them. Each ensures that the menus are properly
  6.  *    enabled and disabled.
  7.  *
  8.  ****/
  9.  
  10. # include    <types.h>
  11. # include    <memory.h>
  12. # include    <packages.h>
  13. # include    <quickdraw.h>
  14. # include    <toolutils.h>
  15. # include    <windows.h>
  16. # include    <dialogs.h>
  17. # include    <menus.h>
  18. # include    <textedit.h>
  19. # include    <string.h>
  20. # include    <files.h>
  21. # include    <resources.h>
  22.  
  23. # include    <iac.h>
  24. # define PUBLIC extern
  25. # include    <Editor.h>
  26.  
  27. #define noErr          0          /* 0 for success */
  28. #define fnfErr          -43     /* File not found */
  29.  
  30. /**
  31.  * Routine: close_doc
  32.  *
  33.  *        This is the code required to close (and save if necessary) a document.
  34.  */
  35.  
  36. # define __SEG__ Main
  37. short    close_doc()
  38. {
  39. win_dataH        the_data_H;            /* data associated with a window */
  40. extentH            the_extH;            /* handle to extent block */
  41. exTable            ext_recs;            /* ptr to array of extents */
  42. TEHandle        TextH;                /* The TextEdit handle */
  43. short            i, item, nm_len;
  44. short            iac_code;            /* result from IAC call */
  45. Str255            st0;
  46.  
  47. extern short        save_doc();        /* saved updated document */
  48.  
  49. extern WindowPtr    myWindow;        /* the text window */
  50.  
  51. # define no    3    /* button id */
  52.  
  53.      the_data_H = (win_dataH) GetWRefCon (myWindow);
  54.     the_extH =     (**the_data_H).the_extents;
  55.     TextH =         (**the_data_H).wind_TEH;
  56.     ext_recs =      *the_extH;
  57.  
  58.     /* check about saving, etc. */
  59.     if ((**the_data_H).dirty)
  60.     {
  61.         nm_len = (**the_data_H).doc_file_nm.length;
  62.         if (nm_len)
  63.         {
  64.             ParamText (&(**the_data_H).doc_file_nm, "", "", "");
  65.         }
  66.         else
  67.         {
  68.             ParamText ("Untitled", "", "", "");
  69.         }
  70.  
  71.         item = StopAlert (SAVE_CHANGES, nil);
  72.         switch (item)
  73.         {
  74.             case ok:
  75.                 save_doc();
  76.                 break;
  77.  
  78.             case cancel:
  79.                 return 0;    /* don't delete extents, etc. */
  80.                 break;
  81.  
  82.             case no:
  83.                 break;
  84.         }
  85.     }
  86.  
  87.     /* shut down extents... */
  88.     for (i=0; i<(**the_data_H).ext_cnt; i++)
  89.     {
  90.         iac_code = iac_remove_dependency(ext_recs[i].src_doc,
  91.                                          (**the_data_H).the_slot,
  92.                                          ext_recs[i].hat_check);
  93.  
  94.         if (iac_code != noErr && iac_code != NO_SUCH_DEP)
  95.         {
  96.             NumToString ((long)iac_code, &st0);
  97.             ParamText (&st0,"Remove Dependency",nil,nil);
  98.             item = StopAlert (IAC_ERR_ALRT, nil);
  99.         }
  100.     }
  101.  
  102.     /* clean up storage associated with window */
  103.     the_data_H = (win_dataH) GetWRefCon(myWindow);
  104.     DisposHandle((Handle) (**the_data_H).the_extents);
  105.     DisposHandle((Handle) the_data_H);
  106.     CloseWindow (myWindow);
  107.  
  108.     /* put menu items into proper states */
  109.     EnableItem (MyMenus[fileMenu], newCommand);
  110.     EnableItem (MyMenus[fileMenu], openCommand);
  111.     DisableItem (MyMenus[fileMenu], closeCommand);
  112.     DisableItem (MyMenus[fileMenu], saveCommand);
  113.     DisableItem (MyMenus[editMenu], 0);        /* nothing to edit */
  114.     DisableItem (MyMenus[optionsMenu], 0);
  115.     DisableItem (MyMenus[fontMenu], 0);
  116.     DisableItem (MyMenus[sizeMenu], 0);
  117.  
  118.     DeleteMenu (linkdDispMenu);                /* no doc, no menu… */
  119.     DisposeMenu (MyMenus[linkdDispMenu]);
  120.     MyMenus[linkdDispMenu] = nil;
  121.     
  122.     DrawMenuBar;
  123. }
  124.  
  125.  
  126. /**
  127.  * Routine: create_doc
  128.  *
  129.  *        This is the code for creating a new document.
  130.  */
  131.  
  132. # define __SEG__ Main
  133. short    create_doc()
  134. {
  135. win_dataH        the_data_H;            /* data associated with a window */
  136.  
  137. extern WindowPtr    myWindow;                /* the text window */
  138. extern void            setup_wind();            /* set up window */
  139.  
  140.     setup_wind();                        /* create window & data structures */
  141.      the_data_H = (win_dataH) GetWRefCon (myWindow);
  142.     (**the_data_H).doc_file_nm.length = 0;    /* no name yet */
  143.  
  144.     /* put menu items into proper states */
  145.     DisableItem (MyMenus[fileMenu], newCommand);
  146.     DisableItem (MyMenus[fileMenu], openCommand);
  147.     EnableItem (MyMenus[fileMenu], closeCommand);
  148.     EnableItem (MyMenus[fileMenu], saveCommand);
  149.     EnableItem (MyMenus[editMenu], 0);        /* now we have stuff to edit */
  150.     EnableItem (MyMenus[optionsMenu], 0);
  151.     EnableItem (MyMenus[fontMenu], 0);
  152.     EnableItem (MyMenus[sizeMenu], 0);
  153.     DrawMenuBar;
  154. }
  155.  
  156.  
  157. /**
  158.  * Routine: open_doc
  159.  *
  160.  *        This is the code required to open a document. After opening the doc,
  161.  *    reading in the text, and reloading the extents, it checks to see if there
  162.  *    are any documents open of which it was a target in a previous life, and
  163.  *    re-establishes those links. After that, it re-starts any links for
  164.  *    which it was the source.
  165.  */
  166.  
  167. # define __SEG__ Main
  168. short    open_doc()
  169. {
  170. IOParam            the_blk;
  171. Handle            txtH;                /* Handle to text itself */
  172. Handle            extRH;                /* extent-resource handle */
  173. long int        txt_size;            /* for TextEdit */
  174. SFReply            a_reply;            /* for SFGetFile */
  175. Point            where;
  176. SFTypeList        the_types;
  177. OSErr            an_err;
  178. short            res_refNum;            /* for resource work */
  179. short            slot_ID, vers, the_ed;        /* for IAC */
  180. short            c_ndx, e_ndx, e_cnt;    /* census-walking loops */
  181. long            t_doc;                /* temporaries to avoid memory problems */
  182. short            t_slot, t_hatchk;
  183. exTable            ext_recs;            /* ptr to extent-array */
  184. win_dataH        the_data_H;            /* data associated with a window */
  185. win_dataH        winRH;                /* window data from saved file */
  186. TEHandle        TextH;                /* The TextEdit handle */
  187. info_tbl        the_census;            /* info for each dependency */
  188.  
  189. short            iac_code = noErr;    /* result from IAC call */
  190. short            doc_count = 0;        /* how many are open? */
  191. short            ext_so_far = 0;        /* counter for 'Links' menu */
  192.  
  193. extern void        setup_wind();        /* set up window */
  194. extern void        add_display_cmd();    /* update 'Links' menu */
  195.  
  196.  
  197.     SetPt (&where, 80, 100);
  198.     the_types[0] = (OSType) 0x54455854;        /* 'TEXT' */
  199.     SFGetFile (&where, "", nil, 1, &the_types[0], nil, &a_reply.good);
  200.     if (a_reply.good)
  201.     {
  202.         /* an_err = SetVol(nil, &a_reply.vRefNum);    /* set default volume */
  203.         an_err = FSOPEN (&a_reply.fName, a_reply.vRefNum, &fRef);
  204.  
  205.         the_blk.ioCompletion = nil;
  206.         the_blk.ioRefNum = fRef;
  207.         an_err = PBGetEOF(&the_blk.qLink, false);
  208.         txt_size = (long int) the_blk.ioMisc;
  209.         txtH = NewHandle (txt_size);
  210.  
  211.         HLock(txtH);
  212.         the_blk.ioCompletion = nil;            /* set up driver parameter block */
  213.         the_blk.ioRefNum =       fRef;
  214.         the_blk.ioBuffer =       *txtH;
  215.         the_blk.ioReqCount =   txt_size;
  216.         the_blk.ioPosMode =    fsFromStart;
  217.         the_blk.ioPosOffset =  0;
  218.         an_err = PBRead(&the_blk.qLink, false);
  219.  
  220.         setup_wind();        /* set up window and TE record */
  221.         SETWTITLE (myWindow, &a_reply.fName);    /* ensure window title OK */
  222.         the_data_H = (win_dataH) GetWRefCon (myWindow);
  223.         TextH = (**the_data_H).wind_TEH;
  224.         TESetText (*txtH, txt_size, TextH);        /* put into TE record */
  225.         HUnlock(txtH);
  226.         DisposHandle (txtH);                    /* no longer needed */
  227.  
  228.         /* get saved data & attach it to the window */
  229.         res_refNum = OPENRESFILE(&a_reply.fName);
  230.         extRH = GetResource ('EXTN', 0);    /* get extents */
  231.         DetachResource (extRH);                /* remove from resource manager */
  232.         DisposHandle((Handle) (**the_data_H).the_extents);    /* kill old table */
  233.         (**the_data_H).the_extents = extRH;
  234.  
  235.         winRH = (win_dataH) GetResource('EXTN', 1);    /* get saved window data */
  236.         (**the_data_H).doc_ID =   (**winRH).doc_ID;
  237.         (**the_data_H).ext_cnt =  (**winRH).ext_cnt;
  238.         DisposHandle((Handle) winRH);    /* no longer needed */
  239.  
  240.         the_blk.ioCompletion = nil;
  241.         the_blk.ioRefNum =       fRef;
  242.         an_err = PBClose(&the_blk.qLink, false);    /* close file */
  243.  
  244.         /*    We get a census of existing dependencies, and check them
  245.          *    against our extent data. For each match, we make that the
  246.          *    "available dependency" and re-establish the link.
  247.          */
  248.         iac_code = iac_census(&doc_count, &the_census);
  249.         if (iac_code == noErr)
  250.         {
  251.             e_cnt = (**the_data_H).ext_cnt;
  252.             HLock(extRH);    /* IAC calls may move memory */
  253.             
  254.             for (c_ndx=0; c_ndx<doc_count; c_ndx++)        /* walk census */
  255.             {
  256.                 ext_recs = *(extentH) extRH;    /* pt to base of table */
  257.                 for (e_ndx=0; e_ndx<e_cnt; e_ndx++)        /* walk extents */
  258.                 {
  259.                     if ((the_census.ext_entry[c_ndx].doc_ID ==
  260.                             ext_recs[e_ndx].src_doc) &&
  261.                         (the_census.ext_entry[c_ndx].hat_check == 
  262.                             ext_recs[e_ndx].hat_check))
  263.                     {
  264.                         /* make this dependency "available" for completion */
  265.                         iac_code = iac_available_dependency(ext_recs[e_ndx].src_doc,
  266.                                                             ext_recs[e_ndx].hat_check);
  267.                         
  268.                         /* complete "available dependency" */
  269.                         t_doc = 0;            /* temps across IAC calls */
  270.                         t_hatchk = 0;        /* have already made extent avail */
  271.                         t_slot = (**the_data_H).the_slot;
  272.                         iac_code = iac_complete_dependency(&t_doc,
  273.                                                            &t_slot,
  274.                                                            &t_hatchk);
  275.                         (**the_data_H).the_slot = t_slot;    /* could change */
  276.  
  277.                         /* read initial copy of data from restarted link */
  278.                         the_ed = 0;
  279.                         iac_code = ext_read(myWindow, &the_ed, e_ndx);
  280.  
  281.                         ext_so_far += 1;
  282.                         add_display_cmd(e_ndx, ext_so_far);    /* add link to menu */
  283.                     }
  284.                 } /* for */
  285.             }    /* got census */
  286.  
  287.             if (e_cnt)    /* restart links for which we are the source */
  288.             {
  289.                 ext_recs = *(extentH) extRH;
  290.                 t_doc =  (**the_data_H).doc_ID;
  291.                 t_slot = (**the_data_H).the_slot;
  292.                 for (e_ndx=0; e_ndx<e_cnt; e_ndx++)
  293.                 {
  294.                     if (ext_recs[e_ndx].src_doc == (**the_data_H).doc_ID)
  295.                     {
  296.                         t_hatchk = ext_recs[e_ndx].hat_check;
  297.                         the_ed = 0;
  298.                         iac_code = iac_add_dependency(&t_doc,
  299.                                                       &t_slot,
  300.                                                       &t_hatchk,
  301.                                                       &the_ed);
  302.                         (**the_data_H).the_slot = t_slot;    /* could change */
  303.  
  304.                         /* write data to restarted dependency */
  305.                         iac_code = ext_write(TextH,
  306.                                              ext_recs[e_ndx].ext_strt,
  307.                                              /* ext_recs[e_ndx].ext_strt - ext_recs[e_ndx].ext_end, */
  308.                                              1,        /* temporary splint */
  309.                                              t_doc,
  310.                                              t_hatchk,
  311.                                              &the_ed);
  312.                         
  313.                         ext_recs[e_ndx].ed_level = the_ed;
  314.                         ext_so_far += 1;
  315.                         add_display_cmd(e_ndx, ext_so_far);    /* add link to menu */
  316.                     }
  317.                 }
  318.             }
  319.             
  320.             HUnlock(extRH);        /* unclutter memory */
  321.         }
  322.  
  323.         /* put menu items into proper states */
  324.         DisableItem (MyMenus[fileMenu], newCommand);
  325.         DisableItem (MyMenus[fileMenu], openCommand);
  326.         EnableItem (MyMenus[fileMenu], closeCommand);
  327.         DisableItem (MyMenus[fileMenu], saveCommand);
  328.         EnableItem (MyMenus[editMenu], 0);        /* now we have stuff to edit */
  329.         EnableItem (MyMenus[optionsMenu], 0);
  330.         EnableItem (MyMenus[fontMenu], 0);
  331.         EnableItem (MyMenus[sizeMenu], 0);
  332.         DrawMenuBar;
  333.     }
  334. }
  335.  
  336.  
  337. /**
  338.  * Routine: save_doc()
  339.  *
  340.  *        This is the code required to save a document.
  341.  */
  342.  
  343. # define __SEG__ Main
  344. short    save_doc()
  345.  
  346. {
  347. win_dataH        the_data_H;            /* data associated with a window */
  348. TEHandle        TextH;                /* The TextEdit handle */
  349. IOParam            the_blk;
  350. Handle            txtH;                /* Handle to text itself */
  351. Handle            tmp_H;                /* temporary for resource work */
  352. short            nm_len;
  353. short            refNum, res_refNum;
  354. Str255            prompt,orig_Name;
  355. SFReply            aReply;
  356. Point            where;
  357. OSErr            anErr;
  358. long int        txt_size;
  359.  
  360.      the_data_H = (win_dataH) GetWRefCon (myWindow);
  361.     TextH =         (**the_data_H).wind_TEH;
  362.     nm_len =     (**the_data_H).doc_file_nm.length;
  363.  
  364.     if (nm_len==0)    /* invoke SFPutFile for file name */
  365.     {
  366.         where.h = 80;
  367.         where.v = 80;
  368.         SFPutFile (&where, "Name your new document", "IAC Doc", nil, &aReply);
  369.         if (aReply.good)
  370.         {
  371.             strcpy(&(**the_data_H).doc_file_nm, &aReply.fName);    /* CHECK! */
  372.         }
  373.         else
  374.         {
  375.             return 0;
  376.         }
  377.     }
  378.  
  379.     anErr = FSOPEN(&(**the_data_H).doc_file_nm, aReply.vRefNum, &refNum);
  380.     if (anErr)    /* may not exist yet.. */
  381.     {
  382.         if (anErr==fnfErr)
  383.         {
  384.             anErr = CREATE(&(**the_data_H).doc_file_nm, aReply.vRefNum, 'IAC1' , 'TEXT');
  385.             anErr = FSOPEN(&(**the_data_H).doc_file_nm, aReply.vRefNum, &refNum);
  386.             (void) CREATERESFILE(&(**the_data_H).doc_file_nm);
  387.         }
  388.         else
  389.         {
  390.             return (anErr);
  391.         }
  392.     }
  393.     res_refNum = OPENRESFILE(&(**the_data_H).doc_file_nm);
  394.     
  395.     /* save text itself in data fork */
  396.     txtH = (**TextH).hText;
  397.     txt_size = GetHandleSize (txtH);
  398.     HLock(txtH);
  399.     the_blk.ioCompletion =    nil;
  400.     the_blk.ioRefNum =         refNum;
  401.     the_blk.ioBuffer =         *txtH;
  402.     the_blk.ioReqCount =     txt_size;
  403.     the_blk.ioPosMode =     fsFromStart;
  404.     the_blk.ioPosOffset =    0;
  405.     anErr = PBWrite(&the_blk.qLink, false);
  406.     HUnlock(txtH);
  407.     
  408.     /* save extents in 'EXTN' resource */
  409.     if (CountResources ('EXTN'))    /* updating existing copy */
  410.     {
  411.         tmp_H = GetResource ('EXTN', 0);    /* read old version */
  412.         RmveResource (tmp_H);                /* kill it */
  413.         tmp_H = GetResource ('EXTN', 1);    /* read old version */
  414.         RmveResource (tmp_H);                /* kill it */
  415.     }
  416.     AddResource ((**the_data_H).the_extents, 'EXTN', 0, nil);
  417.     AddResource ((Handle) the_data_H, 'EXTN', 1, nil);
  418.     UpdateResFile (res_refNum);
  419.     
  420.     /* close up shop till next time */
  421.     the_blk.ioCompletion =    nil;
  422.     the_blk.ioRefNum =        refNum;
  423.     anErr = PBClose(&the_blk.qLink, false);        /* close file */
  424.  
  425.     the_blk.ioCompletion =    nil;
  426.     the_blk.ioNamePtr =        nil;
  427.     the_blk.ioVRefNum =        aReply.vRefNum;
  428.     anErr = PBFlushVol (&the_blk.qLink, false);    /* ensure disk updated */
  429.  
  430.     SETWTITLE (myWindow, &aReply.fName);        /* ensure window title OK */
  431.     
  432.     (**the_data_H).dirty = false;
  433.     return (0);
  434. }
  435.  
  436.  
  437. /**
  438.  * Routine: setup_wind
  439.  *
  440.  *        This allocates the window and creates the TextEdit data structure and
  441.  *    auxiliary data record required.
  442.  */
  443.  
  444. # define __SEG__ Main
  445. void    setup_wind()
  446. {
  447. Rect                txRect;
  448. extentH                temp_extH;                /* handle to extents block */
  449. Str255                tStr;
  450.  
  451. extern    WindowPtr        myWindow;            /* the text window */
  452. extern    WindowRecord    wRecord;
  453. extern    short            the_fNum, the_size;    /* text attributes */
  454. extern    Style            the_style;
  455.  
  456.     myWindow = GetNewWindow(windowID, &wRecord, (WindowPtr) -1);
  457.     SetPort(myWindow);
  458.     txRect = myWindow->portRect;
  459.     InsetRect(&txRect, 4, 0);
  460.     TextH = TENew(&txRect, &txRect);    /* Not growable, so destRect == viewRect */
  461.     curr_ext_no = -1;    /* no 'current extent' yet */
  462.  
  463.     the_data_H = (win_dataH) NewHandle(sizeof(win_data));    /* space for data */
  464.     SetWRefCon (myWindow, (long int) the_data_H);            /* keep with window */
  465.     (**the_data_H).the_slot = 0;        /* slot_ID for this document */
  466.     (**the_data_H).doc_ID =   0;        /* document ID for this doc */
  467.     (**the_data_H).ext_cnt =  0;        /* number of extents with this doc */
  468.     (**the_data_H).wind_TEH = TextH;    /* TE handle for this window */
  469.     (**the_data_H).dirty =      false;
  470.     (**the_data_H).relevent = 0;
  471.  
  472.     /* empty block of extent records */
  473.     temp_extH = (extentH) NewHandle(sizeof(extent));
  474.     (**temp_extH).hat_check = 0;
  475.     (**temp_extH).ed_level =  0;
  476.     (**temp_extH).ext_strt =  0;        /* start & end of extent range */
  477.     (**temp_extH).ext_end =      0;
  478.     (**the_data_H).the_extents = temp_extH;
  479.  
  480.     (**TextH).txFont = the_fNum;        /* set text attributes */
  481.     (**TextH).txSize = the_size;
  482.     (**TextH).txFace = the_style;
  483.     
  484. }
  485.